package yagwl.service.util;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Logger;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

import yagwl.service.fnd.flex.ConfigService;
import yagwl.service.util.svc.BaseException;
import yagwl.service.util.svc.BaseException.ErrorCode;

public class CryptoUtil {

  private static final Logger log = Logger
      .getLogger(CryptoUtil.class.getName());

  static {
    init();
  }

  private static Cipher encCipher;
  private static Cipher decCipher;

  private static void init() {
    String key = ConfigService.getInstance().getValue("EncryptionKey") + "+-";

    byte[] raw = key.getBytes();
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    try {
      encCipher = Cipher.getInstance("AES");
      encCipher.init(Cipher.ENCRYPT_MODE, skeySpec);
      decCipher = Cipher.getInstance("AES");
      decCipher.init(Cipher.DECRYPT_MODE, skeySpec);
    } catch (NoSuchAlgorithmException e1) {
      e1.printStackTrace();
    } catch (NoSuchPaddingException e1) {
      e1.printStackTrace();
    } catch (InvalidKeyException e) {
      e.printStackTrace();
    }
  }

  private static final String PasswordCode = "PWD";

  public static String encryptPassword(String plainText) {
    return encrypt(plainText, PasswordCode);
  }

  public static String decryptPassword(String cipherText) {
    return decrypt(cipherText, PasswordCode);
  }

  private static final String SessionTokenCode = "ST";

  public static String encryptSessionToken(String plainText) {
    return plainText;
    // return encrypt(plainText, SessionTokenCode);
  }

  public static String decryptSessionToken(String cipherText) {
    return cipherText;
    // return decrypt(cipherText, SessionTokenCode);
  }

  public static Long decryptLong(String cipherText, String entityCode) {
    return Long.valueOf(decrypt(cipherText, entityCode));
  }

  public static String encryptLong(Long plainText, String entityCode) {
    return encrypt(plainText.toString(), entityCode);
  }

  public static String decrypt(String cipherText, String entityCode) {
    log.finest(cipherText + ":" + entityCode);
    if (cipherText == null)
      return null;
    byte[] plainTextB = null;
    try {
      byte[] decoded = Base64.decodeBase64(cipherText.getBytes());
      plainTextB = decCipher.doFinal(decoded);
    } catch (IllegalBlockSizeException e) {
      log.severe(e.toString());
      throw new BaseException(ErrorCode.INTERNAL_ENCRYPTION_ERROR, e);
    } catch (BadPaddingException e) {
      log.severe(e.toString());
      throw new BaseException(ErrorCode.INTERNAL_ENCRYPTION_ERROR, e);
    }
    if (plainTextB == null)
      return null;
    String plainText = new String(plainTextB);
    if (entityCode == null)
      return plainText;

    String[] parts = plainText.split(entityCode);
    plainText = parts[0];
    return plainText;
  }

  public static String encrypt(String plainText, String entityCode) {
    log.finest(plainText + ":" + entityCode);
    if (plainText == null)
      return null;
    if (entityCode != null)
      plainText += entityCode;
    byte[] cipherText = null;
    try {
      cipherText = encCipher.doFinal(plainText.getBytes());
    } catch (IllegalBlockSizeException e) {
      log.severe(e.toString());
      throw new BaseException(ErrorCode.INTERNAL_ENCRYPTION_ERROR, e);
    } catch (BadPaddingException e) {
      log.severe(e.toString());
      throw new BaseException(ErrorCode.INTERNAL_ENCRYPTION_ERROR, e);
    }
    byte[] encoded = Base64.encodeBase64(cipherText);
    return new String(encoded);
  }

}
